using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Content;
using System.Collections.Generic;
using WinForms = System.Windows.Forms;

namespace TopShooter
{
	public partial class Game //: Microsoft.Xna.Framework.Game
	{
		static public Game Instance;

		static public bool IsEditorMode = false;

		static public bool IsPaused = false;

		static public bool IsKeyboardDisabled = false;

		public TimeSpan Time;
		public double Seconds;
		private string DebugMessage;
		private TimeSpan _debugMessageExpiration;

		// Resources for drawing.
		private GraphicsDeviceManager _graphics;
		public SpriteBatch SpriteBatch;
		public Drawing.Shapes Shapes;

		// Global content.
		private SpriteFont _hudFont;
		private SpriteFont _bigFont;

		public Portal.PortalTarget CurrentCheckPoint;

		public Scene Scene { get { return Scene.Manager.Instance.CurrentScene; } }

		private const int TargetFrameRate = 60;

		public int MaxScene;

		public ContentManager Content;

		public GameTime GameTime { get { return Drawer.GameTime; } }

		public float TimeDelta { get { return Drawer.TimeDelta; } }

		public RenderControls.GameDraw Drawer;
		WinForms.Form _mainWindow;

		public System.Drawing.Size ScreenSize
		{
			get { return Drawer.Size; }
		}
		public System.Drawing.Point ScreenLocation
		{
			get
			{
				var p = Drawer.PointToScreen(new System.Drawing.Point());
				return p;
			}
		}

		public Game(RenderControls.GameDraw drawer)
		{
			Drawer = drawer;

			_mainWindow = Drawer.Parent as WinForms.Form;

			Instance = this;
			//_graphics = new GraphicsDeviceManager(this);
			//_graphics.PreferredBackBufferWidth = BackBufferWidth;
			//_graphics.PreferredBackBufferHeight = BackBufferHeight;

			Content = new ContentManager(Drawer.Services, "Content");
			Content.RootDirectory = "Content";

			// Framerate differs between platforms.
			//TargetElapsedTime = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / TargetFrameRate);

			//IsMouseVisible = true;
			//IsFixedTimeStep = true;
			//TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 16);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.G, ToggleEditor, false, true);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.S, SaveGameState, false, true);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.L, LoadGameState, false, true);

			Portal.PortalTarget pd = new Portal.PortalTarget("EditorScene,0,W");
		}

		private void SaveGameState(Keys key)
		{
			if (!IsEditorMode)
			{
				Scene.CaptureDynamicContent();
				State s = new State(this);
				s.Save();
				SetDebugMessage("GameStateSaved", 3);


			}
		}
		private void LoadGameState(Keys key)
		{
			if (!IsEditorMode)
			{
				State s = State.Load();
				s.Apply(this);
				SetDebugMessage("GameStateLoaded", 3);
			}
		}

		private void ToggleEditor(Keys key)
		{
			if (IsEditorMode)
			{

				if (Scene.Instance != null)
				{
					Scene.Instance.SaveIfNeeded();
					Scene.Instance.DoNotSaveOnLeaving = true;
				}

				IsEditorMode = false;
				Scene.DynamicContentRegistry.Clear();
				Scene.Instance.Dispose();
				ReloadCurrentScene(false);
			}
			else
			{
				IsEditorMode = true;
				Scene.DynamicContentRegistry.Clear();
				ReloadCurrentScene(false);
				//Controls.EditorWindow.ShowEditor();
			}
		}

		public void LoadContent()
		{
			SpriteBatch = new SpriteBatch(Drawer.GraphicsDevice);
			Shapes = new Drawing.Shapes();

			_hudFont = Content.Load<SpriteFont>("Fonts/Hud");
			_bigFont = Content.Load<SpriteFont>("Fonts/Hud");

			CurrentCheckPoint = new Portal.PortalTarget("0,0,W");

			string[] files = System.IO.Directory.GetFiles(Scene.Manager.SceneFolder);
			MaxScene = files.Length - 1;

			LoadNextScene(CurrentCheckPoint, true);

		}

		static public string LastCommand;



		public void Update(GameTime gameTime)
		{
			Time = gameTime.TotalGameTime;
			Seconds = Time.TotalSeconds;

			HandleInput();
			InputHandler.Instance.CheckForEvents();
			if (!IsPaused)
			{
				if (IsEditorMode)
				{
					UpdateEditorMode(gameTime);
				}
				else
				{
					Scene.Update(gameTime);
				}
			}
		}


		private void UpdateEditorMode(GameTime gameTime)
		{
			Editor.GameEditorPlayer.Instance.Update(gameTime);
		}

		private void HandleInput()
		{
			if (Scene.ReachedPortal != null)
			{
				LoadNextScene(Scene.ReachedPortal, true);
				return;
			}
		}

		public void LoadNextScene(Portal.PortalTarget pd, bool saveCurrentScene)
		{

			if (Scene != null)
			{
				Scene.CaptureDynamicContent();

				if (IsEditorMode || !saveCurrentScene)
				{
					Scene.DynamicContentRegistry.Clear();
				}
				Scene.Dispose();
			}

			Scene.Manager.Instance.LoadSceneByName(pd.SceneName, pd);
		}




		public void ReloadCurrentScene(bool saveCurrentScene)
		{
			LoadNextScene(Scene.SendingPortal, saveCurrentScene);
		}


		public void Draw()
		{
			Drawer.GraphicsDevice.Clear(Color.LightGray);
			SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);

			Scene.Draw(SpriteBatch);

			if (PostDrawCommands != null)
				PostDrawCommands();
			PostDrawCommands = null;

			if (IsEditorMode)
				DrawEditorHud();
			else
				DrawHud();
			SpriteBatch.End();
		}

		public event System.Action PostDrawCommands;

		static private float _timeTilStatusMessageExpires;
		static private string _statusMessage;

		static public void ShowMessage(int seconds, string text)
		{
			_statusMessage = text;
			_timeTilStatusMessageExpires = 1000 * seconds;
		}

		private void DrawEditorHud()
		{
			Rectangle titleSafeArea = Drawer.GraphicsDevice.Viewport.TitleSafeArea;
			Vector2 hudLocation = new Vector2(titleSafeArea.X, titleSafeArea.Y);
			Vector2 center = new Vector2(titleSafeArea.X + titleSafeArea.Width / 2.0f, titleSafeArea.Y + titleSafeArea.Height / 2.0f);
			hudLocation.Y = 600;
			DrawShadowedString(_hudFont, "Scene: " + (this.Scene.Name), hudLocation, Color.Brown);

			if (!String.IsNullOrEmpty(DebugMessage))
			{
				if (Time < _debugMessageExpiration)
				{
					hudLocation.Y += 40;
					DrawShadowedString(_hudFont, DebugMessage, hudLocation, Color.Yellow);
				}
				else
				{
					DebugMessage = null;
				}
			}

			hudLocation.Y += 40;

			if (_timeTilStatusMessageExpires > 0)
			{
				DrawShadowedString(_hudFont, _statusMessage, hudLocation, Color.Yellow);
				_timeTilStatusMessageExpires -= (float)GameTime.ElapsedGameTime.TotalMilliseconds;
			}

		}

		private void DrawHud()
		{
			
			Rectangle titleSafeArea = Drawer.GraphicsDevice.Viewport.TitleSafeArea;
			Vector2 hudLocation = new Vector2(titleSafeArea.X, titleSafeArea.Y);
			Vector2 center = new Vector2(titleSafeArea.X + titleSafeArea.Width / 2.0f, titleSafeArea.Y + titleSafeArea.Height / 2.0f);

			hudLocation.X += 5;
			hudLocation.Y += 5;

			hudLocation.Y = 500;

			if (GodPlayer.Instance.Selections.SelectedEntities.Count > 0)
			{
				Unit u = GodPlayer.Instance.Selections.SelectedEntities[0] as Unit;
				DrawShadowedString(_hudFont, "Unit: " + (u.Name), hudLocation, Color.Brown);
				hudLocation.Y += 20;
				DrawShadowedString(_hudFont, "Health: " + (u.Health), hudLocation, Color.Brown);
				if (u.Weapon != null)
				{
					hudLocation.Y += 20;
					DrawShadowedString(_hudFont, "Damage: " + (u.Weapon.Damage), hudLocation, Color.Brown);
				}
				if (u.Armor != null)
				{
					hudLocation.Y += 20;
					DrawShadowedString(_hudFont, "Armor: " + (u.Armor.Defense), hudLocation, Color.Brown);
				}
			}
			if (!String.IsNullOrEmpty(DebugMessage))
			{
				if (Time < _debugMessageExpiration)
				{
					hudLocation.Y += 40;
					DrawShadowedString(_hudFont, DebugMessage, hudLocation, Color.Yellow);
				}
				else
				{
					DebugMessage = null;
				}
			}
			hudLocation.X = 500;
			hudLocation.Y = 5;
			DrawShadowedString(_hudFont, "Time: " + GameTime.TotalGameTime.ToString("m\\:ss"), hudLocation, Color.LightGreen);

			if (_timeTilStatusMessageExpires > 0)
			{
				DrawShadowedString(_hudFont, _statusMessage, new Vector2(100, 200), Color.Yellow);
				_timeTilStatusMessageExpires -= (float)GameTime.ElapsedGameTime.TotalMilliseconds;
			}
		}

		public void DrawShadowedString(SpriteFont font, string value, Vector2 loc, Color color)
		{
			SpriteBatch.DrawString(font, value, loc + new Vector2(1.0f, 1.0f), Color.Black);
			SpriteBatch.DrawString(font, value, loc, color);
		}
		public void SetDebugMessage(string msg, int duration)
		{
			DebugMessage = msg;
			_debugMessageExpiration = Time + TimeSpan.FromSeconds(duration);
		}
	}
}
